package strategy;

import windows.MainWindow;

import com.stibocatalog.hunspell.Hunspell;

public class Caesar implements AlgorithmInteface {

	private char[] abc;
	private String text;
	private String result;
	private int resultK;
	private int abcLenght;
	private int k;
	private Hunspell.Dictionary dictinary;
	
	private MainWindow ref;

	public Caesar(String text, int k, int language, MainWindow reference) {
		this.text = text;
		this.k = k;
		ref = reference;
		switch (language) {
		case 0:
			System.out.println("English dictionary loaded!");
			abc = Crypto.ENG_ABC;
			abcLenght = Crypto.ENG_LEGHT;
			try {
				dictinary = Hunspell.getInstance().getDictionary("Dictionary/en_US");
			} catch (Exception e) {
				e.printStackTrace();
			}
			break;
		case 1:
			System.out.println("English dictionary loaded!");
			abc = Crypto.HUN_ABC;
			abcLenght = Crypto.HUN_LEGHT;
			try {
				dictinary = Hunspell.getInstance().getDictionary("Dictionary/hu_HU");
			} catch (Exception e) {
				e.printStackTrace();
			}

			break;
		default:
			new Exception("No such language!");
		}

	}

	public Caesar(String text, int language, MainWindow reference) {
		this.text = text;
		k = 0;
		ref = reference;
		abc = Crypto.HUN_ABC;
		abcLenght = Crypto.HUN_LEGHT;
		switch (language) {
		case 0:
			System.out.println("English dictionary loaded!");
			abc = Crypto.ENG_ABC;
			abcLenght = Crypto.ENG_LEGHT;
			try {
				dictinary = Hunspell.getInstance().getDictionary("Dictionary/en_US");
			} catch (Exception e) {
				e.printStackTrace();
			}
			break;
		case 1:
			System.out.println("English dictionary loaded!");
			abc = Crypto.HUN_ABC;
			abcLenght = Crypto.HUN_LEGHT;
			try {
				dictinary = Hunspell.getInstance().getDictionary("Dictionary/hu_HU");
			} catch (Exception e) {
				e.printStackTrace();
			}

			break;
		default:
			new Exception("No such language!");
		}
	}
	
	private boolean contains(char[] chars, char c) {
		boolean cont = false;

		for (int i = 0; i < chars.length; i++) {
			if (c == chars[i])
				return true;
		}

		return cont;
	}

	private char[] createPerm(int tol) {
		char[] codedAbc = new char[abcLenght];

		k = tol;
		int index = k;
		
		int i = 0;
		while (index < abcLenght && i < abcLenght) {
			if (!contains(codedAbc, abc[i])) {
				codedAbc[index] = abc[i];
				index++;
			}
			i++;
		}
		
		index = 0;
		while (index < k && i < abcLenght) {
			if (!contains(codedAbc, abc[i])) {
				codedAbc[index] = abc[i]; // tomb a kodolt abc-vel
				index++;
			}
			i++;
		}
		return codedAbc;
		
	}
	
	private String createResult(char[] codedAbc) {
		result = "";
		char[] inp = text.toCharArray();
		for (int ind = 0; ind < inp.length; ind++) {
			boolean found = false;
			for (int j = 0; j < abc.length; j++) {
				if (inp[ind] == abc[j]) {
					result = result + codedAbc[j];
					found = true;
				} else {
					if (inp[ind] == Character.toUpperCase(abc[j])) {
						result = result + Character.toUpperCase(codedAbc[j]);
						found = true;
					}
				}
			}

			// ha nem talalt megfelelo betut, akkor ugyan ugy irja
			if (!found) {
				result = result + inp[ind];
			}
		}
		
		return result;
	}
	
	@Override
	public void decrypt() {
		char[] codedAbc = createPerm(abcLenght-k);

		resultK = abcLenght-k;
		
		result = createResult(codedAbc);
		
		update();
	}

	@Override
	public void encrypt() {
		char[] codedAbc = createPerm(k);
		
		resultK = k;
		
		result = createResult(codedAbc);
		
		update();
	}

	@Override
	public void update() {
		ref.caesarUpdate(result,resultK);
	}
	
	public String getResult() {
		return result;
	}
	
	public String toString() {
		return result;
	}

	public String cleanString(String input){
//		System.out.println(input);
        String cleaned = "";
        char[] in = input.toLowerCase().toCharArray();
        
        for (int i = 0; i < in.length; i++){
            for (char c : abc) {
            	if (in[i] == c){
                    cleaned = cleaned + in[i];
                }
			}
            
            if (in[i] == ' ' || in[i] == '\n'){
                cleaned = cleaned + " ";
            }
        }

        cleaned = cleaned.replaceAll("\\s+", " ");

        return cleaned;
    }
	
	@Override
	public void autoDecrypt() {
		String tempResult;
		int goodSpell = 0;

		for (int i = 1; i < abcLenght; i++ ) {
			char[] codedAbc = createPerm(i);
			goodSpell = 0;
			
			result = createResult(codedAbc);
			
			tempResult = cleanString(result);
			
			for (String s : tempResult.split(" ")) {
				 if (!dictinary.misspelled(s)) {
					 System.out.println("good: " + s);
					 goodSpell++;
				 } else {
//					 System.out.println(s);
				 }
			}
			
			if ((((double)goodSpell / tempResult.split(" ").length)) > 0.8) {
				resultK = abcLenght - i;
				
				update();
				return;
			}
			System.out.println(goodSpell + " / " + tempResult.split(" ").length + " -> " +tempResult);
			
		}
		
	}
	
	public int getResultK() {
		return resultK;
	}

}
